﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using Unknown.Framework.Develop;

namespace Unknown.Framework.Injection
{
    /// <summary>
    /// 对象工厂类
    /// </summary>
    public static class ObjectFactory
    {
        /// <summary>
        /// 对象配置处理
        /// </summary>
        private static ObjectConfigurationHandler _ObjectConfigurationHandler = new ObjectConfigurationHandler();
        /// <summary>
        /// 自动对象配置处理
        /// </summary>
        private static AutomateConfigurationHandler _AutomateConfigurationHandler = new AutomateConfigurationHandler();

        /// <summary>
        /// 字典
        /// </summary>
        public static Dictionary<string, ObjectIdentify> Dictionary
        {
            get
            {
                return ObjectFactory._ObjectConfigurationHandler.Dictionary;
            }
        }

        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="directory">目录</param>
        /// <param name="searchPattern">匹配字符串</param>
        public static void Configuration(string directory, string searchPattern)
        {
            ObjectFactory._ObjectConfigurationHandler.Build(directory, searchPattern);
        }

        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="directory">目录</param>
        public static void Configuration(string directory)
        {
            ObjectFactory._ObjectConfigurationHandler.Build(directory);
        }

        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="injectionInterfaceType">注入类型</param>
        /// <param name="searchByInterface">根据接口检索</param>
        public static void Configuration(Assembly assembly, Type injectionInterfaceType, bool searchByInterface)
        {
            if ((assembly != null) && (injectionInterfaceType != null))
            {
                Type interfaceType = null;
                try
                {
                    Type[] types = assembly.GetTypes();

                    if (types != null)
                    {
                        foreach (Type type in types)
                        {
                            if ((type.IsPublic) && (!type.IsAbstract) && (!type.IsInterface) && (!type.IsNested) && (!type.IsImport))
                            {
                                Type[] interfaces = type.GetInterfaces();
                                if (interfaces != null)
                                {
                                    for (int i = 0; i < interfaces.Length; i++)
                                    {
                                        interfaceType = interfaces[i];

                                        Type injectionType = interfaceType.GetInterface(injectionInterfaceType.FullName);
                                        if (injectionType != null)
                                        {
                                            ObjectIdentify objectIdentify = new ObjectIdentify();
                                            objectIdentify.Scope = assembly;
                                            objectIdentify.Target = type;

                                            string key = null;
                                            if (searchByInterface)
                                            {
                                                key = interfaceType.FullName;
                                            }
                                            else
                                            {
                                                key = type.FullName;
                                            }

                                            if (!ObjectFactory._ObjectConfigurationHandler.Dictionary.ContainsKey(key))
                                            {
                                                ObjectFactory._ObjectConfigurationHandler.Dictionary.Add(key, objectIdentify);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (ArgumentNullException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(assembly.FullName);
                    if (interfaceType != null)
                    {
                        remarks.Add(interfaceType.FullName);
                    }

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (ArgumentException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(assembly.FullName);
                    if (interfaceType != null)
                    {
                        remarks.Add(interfaceType.FullName);
                    }

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (ReflectionTypeLoadException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(assembly.FullName);
                    if (interfaceType != null)
                    {
                        remarks.Add(interfaceType.FullName);
                    }

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (TargetInvocationException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(assembly.FullName);
                    if (interfaceType != null)
                    {
                        remarks.Add(interfaceType.FullName);
                    }

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
        }

        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="searchByInterface">根据接口检索</param>
        public static void Configuration(Assembly assembly, bool searchByInterface)
        {
            Type injectionInterfaceType = typeof(IObject);
            ObjectFactory.Configuration(assembly, injectionInterfaceType, searchByInterface);
        }

        /// <summary>
        /// 自动配置
        /// </summary>
        /// <param name="directory">目录</param>
        /// <param name="searchPattern">匹配字符串</param>
        /// <param name="searchByInterface">根据接口检索</param>
        public static void AutomateConfiguration(string directory, string searchPattern, bool searchByInterface)
        {
            ObjectFactory._AutomateConfigurationHandler.Build(directory, searchPattern);
            foreach (KeyValuePair<string, AutomateIdentify> pair in ObjectFactory._AutomateConfigurationHandler.Dictionary)
            {
                ObjectFactory.Configuration(pair.Value.Scope, pair.Value.InterfaceTarget, searchByInterface);
            }
        }

        /// <summary>
        /// 自动配置
        /// </summary>
        /// <param name="directory">目录</param>
        /// <param name="searchByInterface">根据接口检索</param>
        public static void AutomateConfiguration(string directory, bool searchByInterface)
        {
            ObjectFactory._AutomateConfigurationHandler.Build(directory);
            foreach (KeyValuePair<string, AutomateIdentify> pair in ObjectFactory._AutomateConfigurationHandler.Dictionary)
            {
                ObjectFactory.Configuration(pair.Value.Scope, pair.Value.InterfaceTarget, searchByInterface);
            }
        }

        /// <summary>
        /// 构建
        /// </summary>
        /// <param name="objectIdentify">对象标识</param>
        /// <returns>实例</returns>
        public static object Build(ObjectIdentify objectIdentify)
        {
            object result = null;

            if ((objectIdentify != null) && (objectIdentify.Scope != null) && (objectIdentify.Target != null))
            {
                try
                {
                    result = objectIdentify.Scope.CreateInstance(objectIdentify.Target.FullName);
                }
                catch (ArgumentNullException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (ArgumentException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (BadImageFormatException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (FileLoadException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (FileNotFoundException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
                catch (MissingMethodException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(objectIdentify.Scope.FullName);
                    remarks.Add(objectIdentify.Target.FullName);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }

            return result;
        }

        /// <summary>
        /// 构建
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>实例</returns>
        public static object Build(string name)
        {
            object result = null;

            if ((ObjectFactory._ObjectConfigurationHandler.Dictionary != null) && (!string.IsNullOrEmpty(name)))
            {
                bool has = ObjectFactory._ObjectConfigurationHandler.Dictionary.ContainsKey(name);
                if (has)
                {
                    ObjectIdentify objectIdentify = ObjectFactory._ObjectConfigurationHandler.Dictionary[name];
                    if (objectIdentify != null)
                    {
                        result = ObjectFactory.Build(objectIdentify);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 构建
        /// </summary>
        /// <param name="type">类</param>
        /// <returns>实例</returns>
        public static object Build(Type type)
        {
            object result = null;

            if (type != null)
            {
                result = ObjectFactory.Build(type.FullName);
            }

            return result;
        }
    }
}
